package net.stuffrepos.bricknetcenter.gui.inventories;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.TreePath;
import net.stuffrepos.bricknetcenter.database.DataManager;
import net.stuffrepos.bricknetcenter.database.schema.Inventory;
import net.stuffrepos.bricknetcenter.database.schema.Transfer;
import net.stuffrepos.bricknetcenter.gui.Icons;
import net.stuffrepos.bricknetcenter.gui.MainFrame;
import net.stuffrepos.bricknetcenter.gui.inventories.BrowserTreeModel.InventoryTreeNode;
import net.stuffrepos.bricknetcenter.gui.inventories.BrowserTreeModel.RootTreeNode;
import net.stuffrepos.bricknetcenter.gui.inventories.BrowserTreeModel.TransferTreeNode;
import net.stuffrepos.util.cache.CacheableValue;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author Eduardo H. Bogoni <eduardobogoni@gmail.com>
 */
public class InventoriesFrame extends javax.swing.JInternalFrame {

    private static final Log log = LogFactory.getLog(InventoriesFrame.class);
    private MainFrame parentFrame;
    private final Action newInventoryAction;
    private final Action newTransferAction;
    private final AbstractAction deleteInventoryAction;
    private final AbstractAction deleteTransferAction;
    private Object selectedNode = null;
    private CacheableValue<InventoryDetailPanel> detailPanel = new CacheableValue<InventoryDetailPanel>() {

        @Override
        protected InventoryDetailPanel calculate() {
            return new InventoryDetailPanel();
        }
    };
    private final CacheableValue<MainDetailPanel> mainDetailPainel = new CacheableValue<MainDetailPanel>() {

        @Override
        protected MainDetailPanel calculate() {
            return new MainDetailPanel();
        }
    };
    private final CacheableValue<TransferDetailPanel> transferDetailPanel = new CacheableValue<TransferDetailPanel>() {

        @Override
        protected TransferDetailPanel calculate() {
            return new TransferDetailPanel(InventoriesFrame.this);
        }
    };

    /** Creates new form ListInventoriesFrame */
    public InventoriesFrame(final MainFrame parentFrame) {
        super("Inventories", true, true, true, true);
        newInventoryAction = new AbstractAction(null, Icons.getIcon("add_inventory.png")) {

            @Override
            public void actionPerformed(ActionEvent e) {
                final NewInventoryDialog dialog = new NewInventoryDialog(parentFrame, false);
                dialog.setVisible(true);
                dialog.addWindowListener(new WindowAdapter() {

                    @Override
                    public void windowClosed(WindowEvent we) {
                        if (dialog.getInventoryName() != null) {
                            try {
                                DataManager.getInstance().createNewInventory(
                                        dialog.getInventoryName(),
                                        dialog.getInventoryComments());
                            } catch (Exception ex) {
                                parentFrame.registerException("Error on creating Inventory", ex);
                            }
                        }
                    }
                });
            }
        };
        newInventoryAction.putValue(Action.SHORT_DESCRIPTION, "New Inventory...");
        deleteInventoryAction = new AbstractAction(null, Icons.getIcon("delete_inventory.png")) {

            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    if (JOptionPane.showConfirmDialog(
                            InventoriesFrame.this,
                            "Are you sure to delete selected inventory(ies)?",
                            "Delete Inventories",
                            JOptionPane.YES_NO_OPTION,
                            JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
                        DataManager.getInstance().deleteInventories(getSelectedInventories());
                    }
                } catch (Exception ex) {
                    parentFrame.registerException("Exception on deleting inventory.", ex);
                }
            }
        };
        deleteInventoryAction.putValue(Action.SHORT_DESCRIPTION, "Delete Inventory");
        deleteInventoryAction.setEnabled(false);
        newTransferAction = new AbstractAction(null, Icons.getIcon("add_transfer.png")) {

            @Override
            public void actionPerformed(ActionEvent e) {
                EventQueue.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        Transfer transfer = new Transfer();
                        transfer.setInventory(getSelectedInventory());
                        transferDetailPanel.getValue().setData(transfer);
                        mainSplit.setRightComponent(transferDetailPanel.getValue());
                    }
                });
            }
        };
        newTransferAction.putValue(Action.SHORT_DESCRIPTION, "New Movimentation");
        newTransferAction.setEnabled(false);

        deleteTransferAction = new AbstractAction(null, Icons.getIcon("delete_transfer.png")) {

            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    if (JOptionPane.showConfirmDialog(
                            InventoriesFrame.this,
                            "Are you sure to delete selected transfer(s)?",
                            "Delete Transfers",
                            JOptionPane.YES_NO_OPTION,
                            JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
                        DataManager.getInstance().deleteTransfers(getSelectedTransfers());
                    }
                } catch (Exception ex) {
                    parentFrame.registerException("Exception on deleting transfer.", ex);
                }
            }
        };
        deleteTransferAction.putValue(Action.SHORT_DESCRIPTION, "Delete Transfer");
        deleteTransferAction.setEnabled(false);

        this.parentFrame = parentFrame;
        initComponents();
        browser.addTreeSelectionListener(new TreeSelectionListener() {

            @Override
            public void valueChanged(TreeSelectionEvent e) {
                if (e == null || e.getNewLeadSelectionPath() == null || e.getNewLeadSelectionPath().getPathCount() == 0) {
                    setSelectedNode(null);
                } else if (e.getNewLeadSelectionPath().getPathCount() > 0) {
                    setSelectedNode(
                            e.getNewLeadSelectionPath().getPath()[e.getNewLeadSelectionPath().getPath().length - 1]);
                }
            }
        });
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                browser.setSelectionInterval(0, 0);
            }
        });
    }

    private void showInventoryDetail(Inventory inventory) {
        detailPanel.getValue().setInventory(inventory);
        mainSplit.setRightComponent(detailPanel.getValue());
    }

    private void showTransferDetail(Transfer transfer) {
        transferDetailPanel.getValue().setData(transfer);
        mainSplit.setRightComponent(transferDetailPanel.getValue());
    }

    private void showMainDetail() {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                mainSplit.setRightComponent(mainDetailPainel.getValue());
            }
        });
    }

    private Inventory getSelectedInventory() {
        if (selectedNode instanceof InventoryTreeNode) {
            return ((InventoryTreeNode) selectedNode).getInventory();
        } else {
            throw new ClassCastException("Selected node is not a Inventory");
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainSplit = new javax.swing.JSplitPane();
        browseScrollPane = new javax.swing.JScrollPane();
        browser = new javax.swing.JTree();
        toolBar = new javax.swing.JToolBar();
        newInventoryButton = new javax.swing.JButton();
        jButton1 = new javax.swing.JButton();
        newMovimentationButton = new javax.swing.JButton();
        deleteTransferButton = new javax.swing.JButton();

        mainSplit.setDividerLocation(100);

        browser.setModel(new BrowserTreeModel());
        browser.setScrollsOnExpand(true);
        browseScrollPane.setViewportView(browser);

        mainSplit.setLeftComponent(browseScrollPane);

        toolBar.setFloatable(false);
        toolBar.setRollover(true);

        newInventoryButton.setAction(getNewInventoryAction());
        newInventoryButton.setFocusable(false);
        newInventoryButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        newInventoryButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        newInventoryButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newInventoryButtonActionPerformed(evt);
            }
        });
        toolBar.add(newInventoryButton);

        jButton1.setAction(getDeleteInventoryAction());
        jButton1.setFocusable(false);
        jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });
        toolBar.add(jButton1);

        newMovimentationButton.setAction(getNewMovimentationAction());
        newMovimentationButton.setFocusable(false);
        newMovimentationButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        newMovimentationButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        toolBar.add(newMovimentationButton);

        deleteTransferButton.setAction(deleteTransferAction);
        deleteTransferButton.setFocusable(false);
        deleteTransferButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        deleteTransferButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        toolBar.add(deleteTransferButton);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(mainSplit, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE)
            .addComponent(toolBar, javax.swing.GroupLayout.DEFAULT_SIZE, 401, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(toolBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(mainSplit, javax.swing.GroupLayout.DEFAULT_SIZE, 581, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void newInventoryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newInventoryButtonActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_newInventoryButtonActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_jButton1ActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane browseScrollPane;
    private javax.swing.JTree browser;
    private javax.swing.JButton deleteTransferButton;
    private javax.swing.JButton jButton1;
    private javax.swing.JSplitPane mainSplit;
    private javax.swing.JButton newInventoryButton;
    private javax.swing.JButton newMovimentationButton;
    private javax.swing.JToolBar toolBar;
    // End of variables declaration//GEN-END:variables

    private Action getNewInventoryAction() {
        return newInventoryAction;
    }

    private Action getDeleteInventoryAction() {
        return deleteInventoryAction;
    }

    public Action getNewMovimentationAction() {
        return newTransferAction;
    }

    private void setSelectedNode(Object node) {

        this.selectedNode = node;
        boolean isSelectedInventory = false;
        boolean isSelectedTransfer = false;

        if (this.selectedNode == null || node instanceof RootTreeNode) {
            showMainDetail();
        } else if (node instanceof InventoryTreeNode) {
            showInventoryDetail(((InventoryTreeNode) node).getInventory());
            isSelectedInventory = true;
        } else if (node instanceof TransferTreeNode) {
            showTransferDetail(((TransferTreeNode) node).getTransfer());
            isSelectedTransfer = true;
        }

        deleteInventoryAction.setEnabled(isSelectedInventory);
        newTransferAction.setEnabled(isSelectedInventory);
        deleteTransferAction.setEnabled(isSelectedTransfer);
    }

    public void showPanelFromSelectedNode() {
        setSelectedNode(this.selectedNode);
    }

    private Collection<Inventory> getSelectedInventories() {
        List<Inventory> inventories = new LinkedList<Inventory>();
        for (TreePath path : browser.getSelectionPaths()) {
            Object node = path.getPathComponent(path.getPathCount() - 1);
            if (node instanceof InventoryTreeNode) {
                inventories.add(((InventoryTreeNode) node).getInventory());
            }
        }
        return inventories;
    }

    private Collection<Transfer> getSelectedTransfers() {
        List<Transfer> transfers = new LinkedList<Transfer>();
        for (TreePath path : browser.getSelectionPaths()) {
            Object node = path.getPathComponent(path.getPathCount() - 1);
            if (node instanceof TransferTreeNode) {
                transfers.add(((TransferTreeNode) node).getTransfer());
            }
        }
        return transfers;
    }
}
